package com.dmz.workflow.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dmz.workflow.base.BaseServiceImpl;
import com.dmz.workflow.constant.CommonConstants;
import com.dmz.workflow.constant.ProcessDefinitionConstants;
import com.dmz.workflow.dao.WorkflowNodeInfoMapper;
import com.dmz.workflow.service.WorkflowNodeInfoService;
import com.dmz.workflow.util.ObjectUtils;
import com.echronos.workflow.constant.ProcessConstants;
import com.dmz.workflow.entity.IntermediateNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class WorkflowNodeInfoServiceImpl extends BaseServiceImpl<WorkflowNodeInfoMapper, IntermediateNode> implements WorkflowNodeInfoService {

    @Autowired
    WorkflowNodeInfoMapper workflowNodeInfoMapper;

    @Override
    public int updateNodeArriveStatus(String processInstanceId, String taskDefinitionKey, String nodeType, String taskId, Integer isArrive) {
        LambdaUpdateWrapper<IntermediateNode> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(IntermediateNode::getProcessInstanceId, processInstanceId);
        if (ObjectUtils.isNotEmpty(taskDefinitionKey)) {
            lambdaUpdateWrapper.eq(IntermediateNode::getNodeId, taskDefinitionKey);
        }
        if (ObjectUtils.isNotEmpty(nodeType)) {
            lambdaUpdateWrapper.eq(IntermediateNode::getNodeType, nodeType);
        }

        IntermediateNode intermediateNode = new IntermediateNode();
        intermediateNode.setIsArrive(isArrive);
        if (ObjectUtils.isNotEmpty(taskId)) {
            intermediateNode.setTaskId(taskId);
        }
        return workflowNodeInfoMapper.update(intermediateNode, lambdaUpdateWrapper);
    }

    @Override
    public int updateNodeTaskIdStatus(String processInstanceId, String taskDefinitionKey, String taskId, Integer arriveStatus) {
        LambdaUpdateWrapper<IntermediateNode> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(IntermediateNode::getNodeId, taskDefinitionKey)
                .eq(IntermediateNode::getProcessInstanceId, processInstanceId);
        IntermediateNode intermediateNode = new IntermediateNode();
        intermediateNode.setTaskId(taskId);
        if (ObjectUtils.isNotEmpty(arriveStatus)) {
            intermediateNode.setIsArrive(arriveStatus);
        }
        return workflowNodeInfoMapper.update(intermediateNode, lambdaUpdateWrapper);
    }

    @Override
    public int updateNodeTaskIdCaseRefuseOperation(String processInstanceId, String taskDefinitionKey, String taskId) {
        LambdaUpdateWrapper<IntermediateNode> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(IntermediateNode::getNodeId, taskDefinitionKey)
                .eq(IntermediateNode::getProcessInstanceId, processInstanceId);
        IntermediateNode intermediateNode = new IntermediateNode();
        intermediateNode.setTaskId(taskId);
        intermediateNode.setIsArrive(ProcessConstants.NODE_ARRIVED_STATUS);

        return workflowNodeInfoMapper.update(intermediateNode, lambdaUpdateWrapper);
    }

    @Override
    public int updateNodeCaseRefuseOperation(String processInstanceId) {
        LambdaUpdateWrapper<IntermediateNode> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(IntermediateNode::getIsArrive, ProcessConstants.NODE_NOT_ARRIVE_STATUS)
                .eq(IntermediateNode::getProcessInstanceId, processInstanceId);
        IntermediateNode intermediateNode = new IntermediateNode();
        intermediateNode.setIsDeleted(CommonConstants.DATA_DELETED_STATUS);
        return workflowNodeInfoMapper.update(intermediateNode, lambdaUpdateWrapper);
    }

    @Override
    public List<IntermediateNode> selectIntermediateNodesByProcessInstanceId(String processInstanceId) {
        LambdaQueryWrapper<IntermediateNode> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(IntermediateNode::getProcessInstanceId, processInstanceId)
                .ne(IntermediateNode::getIsDeleted, CommonConstants.DATA_DELETED_STATUS)
                .orderByAsc(IntermediateNode::getSort);
        return workflowNodeInfoMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public int updateRepealProcessNode(String processInstanceId) {
        LambdaUpdateWrapper<IntermediateNode> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(IntermediateNode::getProcessInstanceId, processInstanceId)
                .eq(IntermediateNode::getIsArrive, ProcessConstants.NODE_NOT_ARRIVE_STATUS);
        IntermediateNode intermediateNode = new IntermediateNode();
        intermediateNode.setIsDeleted(CommonConstants.DATA_DELETED_STATUS);
        return workflowNodeInfoMapper.update(intermediateNode, lambdaUpdateWrapper);
    }

    @Override
    public List<IntermediateNode> queryReachableBackNodes(String processInstanceId) {
        LambdaQueryWrapper<IntermediateNode> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(IntermediateNode::getProcessInstanceId, processInstanceId)
                .eq(IntermediateNode::getIsArrive, ProcessConstants.NODE_ARRIVED_STATUS)
                .ne(IntermediateNode::getNodeId, ProcessDefinitionConstants.START_NODE_NAME)
                .ne(IntermediateNode::getNodeType, ProcessDefinitionConstants.BACK_NODE)
                .ne(IntermediateNode::getIsDeleted, CommonConstants.DATA_DELETED_STATUS);
        return workflowNodeInfoMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public List<IntermediateNode> queryBackNodes(String processInstanceId, Integer tarSort) {
        LambdaQueryWrapper<IntermediateNode> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(IntermediateNode::getProcessInstanceId, processInstanceId)
                .ge(IntermediateNode::getSort, tarSort)
                .ne(IntermediateNode::getNodeType, ProcessDefinitionConstants.BACK_NODE)
                .ne(IntermediateNode::getIsDeleted, CommonConstants.DATA_DELETED_STATUS)
                .orderByAsc(IntermediateNode::getSort);
        return workflowNodeInfoMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public int queryBackNodesNum(String processInstanceId) {
        LambdaQueryWrapper<IntermediateNode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IntermediateNode::getProcessInstanceId, processInstanceId)
                .eq(IntermediateNode::getNodeType, ProcessDefinitionConstants.BACK_NODE);
        return workflowNodeInfoMapper.selectCount(queryWrapper);
    }

    @Override
    public int queryProcessNodesNum(String processInstanceId) {
        LambdaQueryWrapper<IntermediateNode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IntermediateNode::getProcessInstanceId, processInstanceId);
        return workflowNodeInfoMapper.selectCount(queryWrapper);
    }
}
